package stuttgart.uni.locationtracker;

import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.location.Location;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;

public class LocationTrackerService extends Service {
	
	final RemoteCallbackList<IRemoteServiceCallback> mCallbacks= new RemoteCallbackList<IRemoteServiceCallback>();
	
	
	
	private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        public void registerCallback(IRemoteServiceCallback cb) {
            if (cb != null){
            	mCallbacks.register(cb);
            }
        }
        public void unregisterCallback(IRemoteServiceCallback cb) {
            if (cb != null){
            	mCallbacks.unregister(cb);
            }
        }
        
        public void requestFriendListUpdate(){
        	clientThread.myHandler.sendEmptyMessage(REQUEST_FRIENDLIST_UPDATE);
        }
        
        public void requestFriendDataUpdate(String id){
        	Message msg = Message.obtain(clientThread.myHandler, REQUEST_CLIENT_UPDATE, id);
        	clientThread.myHandler.sendMessage(msg);
        }
        
        public void requestLogout(){
        	clientThread.myHandler.sendEmptyMessage(REQUEST_LOGOUT);
        	stopSelf();
        }
    };
    
    private Notification notification;
    //private LocationTrackerClient locationTrackerClient;
    private String ipAddress;
    private String username;
   
    
    public static final int REQUEST_CLIENT_UPDATE = 0;
	public static final int REQUEST_FRIENDLIST_UPDATE = 1;
	public static final int REQUEST_LOGOUT = 2;
    
	private ClientThread clientThread;
	
	private class ClientThread extends Thread{
		
		public ClientHandler myHandler;
		
		public void run(){
			Looper.prepare();
			myHandler = new ClientHandler();
			Looper.loop();
		}
	}
	
	private class ClientHandler extends Handler{
		
		public LocationTrackerClient locationTrackerClient;
		
		public ClientHandler(){
			locationTrackerClient = new LocationTrackerClient(LocationTrackerService.this,ipAddress,username);
		}
		
		@Override
		public void handleMessage(Message msg) {
			// TODO Auto-generated method stub
			super.handleMessage(msg);
			
			switch (msg.what){
			
			case REQUEST_CLIENT_UPDATE:
				float[] result = new float[1];
	        	TrackingData friendData = locationTrackerClient.getFriendUpdateFromServer((String)msg.obj);
	        	TrackingData ownData = locationTrackerClient.getRealGpsData();
	        	Location.distanceBetween(ownData.getLatitude(), ownData.getLongitude(), friendData.getLatitude(), friendData.getLongitude(), result);
	        	updateFriendValues(friendData,result[0]);
				break;
			
			case REQUEST_FRIENDLIST_UPDATE:
				updateFriendList(locationTrackerClient.getFriendListFromServer());	
				break;
				
			case REQUEST_LOGOUT:
				Log.d("LocationTrackerService", "requestLogout() Handler");
				System.out.println("locationTrackerClient is: "+ locationTrackerClient);
				locationTrackerClient.logoutFromServer();
				locationTrackerClient.close();
				

				Looper.myLooper().quit();
				break;

			default:
				break;
			}
		}
	}
	
    @Override
	public void onCreate() {
    	
    	//notification for start Foreground
    	notification = new Notification.Builder(this)
		.setOngoing(true)
		.setContentTitle("LocationTracker")
		.setContentText("Tracking Location")
		.setSmallIcon(R.drawable.notification_icon)
		.build();
    	
    	/*
    	 * For old Devices, API Level 11
    	 * 
    	notification = new Notification.Builder(this)
		.setOngoing(true)
		.setContentTitle("LocationTracker")
		.setContentText("Tracking Location")
		.setSmallIcon(R.drawable.notification_icon)
		.getNotification();
		*/
	}
    
    
    
    @Override
	public int onStartCommand(Intent intent, int flags, int startId) {
    	
    	startForeground(1, notification);
    	ipAddress = intent.getExtras().getString("SERVER_IP_ADDRESS");
    	username = intent.getExtras().getString("USERNAME");
    	
    	clientThread = new ClientThread();
    	clientThread.start();
    	
		return Service.START_REDELIVER_INTENT;
	}
    
    
    
    
	//Funktionen welche die gleichnamigen Funktionen des Activity aufrufen
    //und mit Werten versorgen
    public void updateOwnValues(TrackingData trackingData){
    	final int N = mCallbacks.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).updateOwnValues(trackingData);
            } catch (RemoteException e) {
                Log.d("LocationTrackingService","RemoteException in updateOwnValues");
            }
        }
        mCallbacks.finishBroadcast();
    }
    
    public void updateFriendValues(TrackingData trackingData, float distanceToFriend){
    	final int N = mCallbacks.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).updateFriendValues(trackingData,distanceToFriend);
            } catch (RemoteException e) {
                Log.d("LocationTrackingService","RemoteException in updateOwnValues");
            }
        }
        mCallbacks.finishBroadcast();
    }
    
    public void updateFriendList(FriendList friendList){
    	final int N = mCallbacks.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).updateFriendList(friendList);
            } catch (RemoteException e) {
                Log.d("LocationTrackingService","RemoteException in updateOwnValues");
            }
        }
        mCallbacks.finishBroadcast();
    }
   
    public void updatePacketReductionRatio(double packetReductionRatio){
    	final int N = mCallbacks.beginBroadcast();
        for (int i=0; i<N; i++) {
            try {
                mCallbacks.getBroadcastItem(i).updatePacketReductionRatio(packetReductionRatio);
            } catch (RemoteException e) {
                Log.d("LocationTrackingService","RemoteException in packetReductionRatio");
            }
        }
        mCallbacks.finishBroadcast();
    }
    
    
    @Override
	public void onDestroy(){
		stopForeground(true);
		
		if(mCallbacks!=null){
			mCallbacks.kill();
		}
		
		clientThread.myHandler.locationTrackerClient.close();
		
	}

	@Override
    public IBinder onBind(Intent intent) {
		Log.d("LocationTrackingService"," on bind");
		return mBinder;
    }
	
}
